#include "TaskQueue.hpp"
#include "MutexLock.hpp"
#include <iostream>

using std::cout;
using std::endl;


namespace wd
{

TaskQueue::TaskQueue(int sz)
: _queSize(sz)
, _mutex()
, _notFull(_mutex)
, _notEmpty(_mutex)
, _flag(true)
{}

bool TaskQueue::empty() const
{
    return _que.size() == 0;
}

bool TaskQueue::full() const
{
    return _que.size() == _queSize;
}

//运行在生产者线程
void TaskQueue::push(ElemType e)
{
    MutexLockGuard autolock(_mutex);
    while(full()) {
        //当队列已满时，只能等待
        _notFull.wait();
    }
    //任务队列有空间时，可以继续往其中放数据
    _que.push(e);//在队列的尾部添加元素

    //通知消费者线程取数据
    _notEmpty.notify();
}

//运行在消费者线程
ElemType TaskQueue::pop()
{
    //autolock是一个局部对象,当pop函数执行结束时
    //该对象一定会被销毁, 在销毁时就会完成解锁操作
    MutexLockGuard autolock(_mutex);
    while(_flag && empty()) {
        //当队列为空时，只能等待
        _notEmpty.wait();
    }
    
    if(_flag) {
        //获取队头的元素
        ElemType tmp = _que.front();
        _que.pop();//删除队列头部的元素

        //任务队列不再是已满的状态，需要向生产者线程发通知
        _notFull.notify();

        return tmp;
    }else {
        return nullptr;
    }
}

void TaskQueue::wakeup()
{
    _flag =false;
    _notEmpty.notifyAll();
}


}//end of namespace wd
